package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.common.constants.message.NewsAutoScanConstants;
import com.heima.common.exception.config.CustException;
import com.heima.feigns.article.ArticleFeign;
import com.heima.feigns.wemedia.WemediaFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.dtos.ApArticleDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.media.pojos.WmNews;
import com.heima.model.media.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j

public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
    @Autowired
    WemediaFeign wemediaFeign;
    @Autowired
    AdChannelMapper adChannelMapper;
    @Autowired
    ArticleFeign articleFeign;
    @Value("${file.oss.web-site}")
    private String website;
    @Autowired
    AdSensitiveMapper adSensitiveMapper;
    @Autowired
    GreenTextScan greenTextScan;
    @Autowired
    GreenImageScan greenImageScan;
    @Autowired
    KafkaTemplate kafkaTemplate;

    /**
     * 自媒体文章审核,发布文章到APP端
     *
     * @param wmNewsId
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void autoScanByMediaNewsId(Integer wmNewsId) {

        //0参数校验
        if (wmNewsId == null) {
            log.error("*****WemediaNewsAutoScanServiceImp autoScanByMediaNewsId wmNewsId  null*****");
            return;
        }
        //1根据文章的id查询WmNews数据
        WmNews wmNews = wemediaFeign.findById(wmNewsId);
        if (wmNews == null) {
            log.error("*****WemediaFeign findById WmNews null*****");
        }

        //2判断文章状态=4（人工审核通过）且发布时间小于等于当前时间，直接发布文章（保存三张表数据）
        Integer status = wmNews.getStatus();
        long time = wmNews.getPublishTime().getTime();
        if (status == WmNews.Status.ADMIN_SUCCESS.getCode() && time <= System.currentTimeMillis()) {
            //保存数据
            publishArticle(wmNews);
            log.info("人工审核通过，文章已发布，id:{}",wmNewsId);
            return;
        }

        //3判断文章状态=8（审核通过）且发布时间小于等于当前时间,直接发布文章（保存三张表数据）
        if (status == WmNews.Status.SUCCESS.getCode() && time <= System.currentTimeMillis()) {
            publishArticle(wmNews);
            log.info("审核通过，文章已发布，id:{}",wmNewsId);
            return;
        }
        //4判断文章状态=1(待审核状态)根据审核的结果修改WmNews状态，拒绝理由，APP文章id
        if (status == WmNews.Status.SUBMIT.getCode()) {
            Map<String, Object> contentAndImagesResult = handleTextAndImages(wmNews);

            //4.1审核文章：自管理敏感词
            boolean result = handleSensitive((String) contentAndImagesResult.get("content"), wmNews);
            if (!result) return;

            //4.2审核文章：阿里云内容反垃圾审核（block/review/pass）
            boolean textResult = handleTextScan((String) contentAndImagesResult.get("content"), wmNews);
            if (!textResult) return;
            //4.3审核文章：阿里云图片审核
            boolean imagesResult = handleImagesScan((List) contentAndImagesResult.get("images"), wmNews);
            if (!imagesResult) return;
        }

        //5.审核通过，判断当前文章的发布时间是否>当前时间，修改WmNews状态为8
        if (time > System.currentTimeMillis()) {
            updateWmNews(wmNews, WmNews.Status.SUCCESS.getCode(), "审核通过等待发布");
            return;
        }
        //6.直接发布文章（保存三张表数据），修改WmNews状态为9
        Long articleId = publishArticle(wmNews);

    }

    /**
     * 远程调用保存ApArticle 三张表数据
     *
     * @param wmNews
     * @return
     */
    private Long publishArticle(WmNews wmNews) {
        //远程调用保存ApArticle 三张表数据，将article_id存到result的Data中
        ResponseResult result = saveApArticle(wmNews);
        if (result.getCode() != 0) {
            CustException.cust("保存文章失败");
        }
        //设置article_id
        wmNews.setArticleId((Long) result.getData());
        updateWmNews(wmNews, WmNews.Status.PUBLISHED.getCode(), "发布成功");
        //7.生成文章对应的静态页面（发消息-异步）
        HashMap<String,Long> map = new HashMap<>();
        map.put("articleId",wmNews.getArticleId());
        kafkaTemplate.send(NewsAutoScanConstants.GENERATE_PAGE_TOPIC,JSON.toJSONString(map));

        //TODO 8同步索引库

        return wmNews.getArticleId();
    }

    /**
     * 远程调用保存三张表数据，将article_id存到result的Data中
     *
     * @param wmNews
     * @return
     */
    private ResponseResult saveApArticle(WmNews wmNews) {
        ApArticleDto apArticleDto = new ApArticleDto();
        BeanUtils.copyProperties(wmNews, apArticleDto);
        apArticleDto.setId(wmNews.getArticleId());

        //查看当前自媒体账号状态是否正常
        WmUser wmUser = wemediaFeign.findWmUserById(wmNews.getUserId());
        if (wmUser.getStatus() != 9 || wmNews == null) {
            CustException.cust(AppHttpCodeEnum.NO_OPERATOR_AUTH, "当前账号被禁用，请联系管理员");
        }
        //作者昵称
        apArticleDto.setAuthorName(wmUser.getName());
        //频道
        AdChannel adChannel = adChannelMapper.selectById(wmNews.getChannelId());
        if (adChannel!=null&& StringUtils.isNotBlank(adChannel.getName())){
            apArticleDto.setChannelId(adChannel.getId());
            apArticleDto.setChannelName(adChannel.getName());
        }
        apArticleDto.setLayout(wmNews.getType());
        apArticleDto.setFlag(0);
        apArticleDto.setLikes(0);
        apArticleDto.setCollection(0);
        apArticleDto.setComment(0);
        apArticleDto.setViews(0);
        apArticleDto.setCreatedTime(new Date());
        apArticleDto.setSyncStatus(true);
        apArticleDto.setOrigin(true);

        return articleFeign.saveApArticle(apArticleDto);

    }

    /**
     * 阿里云图片审核
     *
     * @param images
     * @param wmNews
     * @return
     */
    private boolean handleImagesScan(List images, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenImageScan.imageUrlScan(images);
            if (map.get("suggestion").equals("block")) {//审核失败
                flag = false;
                log.error("阿里云审核:图片违规");
                updateWmNews(wmNews, 2, "图片违规");
            }
            if (map.get("suggestion").equals("review")) {//审核失败
                flag = false;
                log.error("阿里云审核:需要人工审核");
                updateWmNews(wmNews, 3, "阿里云审核失败，需要人工审核");
            }
        } catch (Exception e) {
            log.error("阿里云图片审核失败，需要人工审核");
            flag = false;
            updateWmNews(wmNews, 3, "阿里云审核失败，需要人工审核");
        }
        return flag;
    }

    /**
     * 阿里云内容反垃圾审核
     *
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handleTextScan(String content, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(content);
            if (map.get("suggestion").equals("block")) {//审核失败
                flag = false;
                log.error("阿里云审核:文本中有敏感词汇");
                updateWmNews(wmNews, 2, "文本中有敏感词汇");
            }
            if (map.get("suggestion").equals("review")) {//审核失败
                flag = false;
                log.error("阿里云审核:需要人工审核");
                updateWmNews(wmNews, 3, "阿里云审核失败，需要人工审核");
            }
        } catch (Exception e) {
            log.error("阿里云内容反垃圾审核失败");
            flag = false;
            updateWmNews(wmNews, 3, "阿里云审核失败，需要人工审核");

        }

        return flag;
    }

    /**
     * 自管理敏感词
     *
     * @param content
     * @param wmNews
     * @return
     */

    private boolean handleSensitive(String content, WmNews wmNews) {
        boolean flag = true;
        //查询所有敏感词
        List<String> words = adSensitiveMapper.findAllSensitive();
        SensitiveWordUtil.initMap(words);
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if (map.size() > 0) { //包含的敏感词
            flag = false;
            //修改wmNews的状态为2，给理由
            log.error("文章中包含敏感词", map);
            updateWmNews(wmNews, 2, "文章中包含敏感词" + map);
        }
        return flag;
    }

    /**
     * 修改自媒体文章状态
     *
     * @param wmNews
     * @param status
     * @param reason
     */
    private void updateWmNews(WmNews wmNews, int status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        //apArticle 文章id,通过才有
        ResponseResult result = wemediaFeign.updateWmNews(wmNews);
        if (result.getCode() != 0) {
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID, "修改自媒体文章状态失败");
        }
    }

    /**
     * 解析content的文本和图片列表
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        //获取文章内容，并转换对象
        String content = wmNews.getContent();
        if (StringUtils.isBlank(content) || content.length() > 10000) {
            CustException.cust("文章内容不合法");
        }
        List<Map> contents = JSON.parseArray(content, Map.class);
        //解析内容文本
        //文章和标题解析
        String title = wmNews.getTitle();
        String contentText = contents.stream().filter(x -> x.get("type").equals("text"))
                .map(y -> y.get("value").toString())
                .collect(Collectors.joining("_"));
        String text = title + content;

        //文章内容图片,带前缀website
        List<String> contentimages = contents.stream().filter(x -> x.get("type").equals("image"))
                .map(y -> y.get("value").toString())
                .collect(Collectors.toList());
        //文章封面图片
        List<String> collectimages = Stream.of(wmNews.getImages().split(","))
                .map(x -> website + x)
                .collect(Collectors.toList());
        contentimages.addAll(collectimages);
        //图片去重
        List<String> images = contentimages.stream().distinct().collect(Collectors.toList());
        //封装结果返回
        Map<String, Object> map = new HashMap<>();
        map.put("content", contentText);
        map.put("images", images);

        return map;
    }


}
